import React, { useReducer } from "react";

const COMM_API ="call api";

import {http} from 'cess-core';

import {createCessContext} from './context';

const callApi = (config) => {
	return http(config);
};

//网络请求中间件
var api = state => next => action => {
	let commAPIConfig = action[COMM_API];
	if (typeof commAPIConfig === 'undefined') {
		return next(action)
	}

	if (typeof commAPIConfig === 'function') {
		commAPIConfig = commAPIConfig(state)
	}

	const {types} = commAPIConfig;

	if (!Array.isArray(types) || types.length !== 3) {
		throw new Error('Expected an array of three action types.')
	}
	if (!types.every(type => typeof type === 'string')) {
		throw new Error('Expected action types to be strings.')
	}

	const actionWith = data => {
		const finalAction = Object.assign({}, action, data);
		delete finalAction[COMM_API];
		return finalAction
	};

	const [ requestType, successType, failureType ] = types;
	next(actionWith({ type: requestType, config:commAPIConfig.config}));

	//url 加 contextPath 前缀
	var httpConfig = {...commAPIConfig.config,url:commAPIConfig.config.url};
	return callApi(httpConfig).then(
		response => next(actionWith({
			result:response,
			type: successType
		})),
		error => next(actionWith({
			type: failureType,
			error
		}))
	)
}


var reducerInAction = ({state, dispatch}) => next => action => {
	if (typeof action === 'function') {
		return action({dispatch, state});
	}
	return next(action);
}

function isPromise(obj) {
	return (
		!!obj &&
		(typeof obj === "object" || typeof obj === "function") &&
		typeof obj.then === "function"
	);
}

export function useCessReducer({reducer, initstate, name}){

	//发起真正的 dispatch
	var reducerMiddleware = ({state, dispatch}) => next => action => {
		dispatch(action);
	}

	//设置默认中间件
	const middleware = [reducerInAction, api, reducerMiddleware];

	let isCheckedMiddleware = false;
	const middlewareReducer = function({state, action, dispatch}) {

		if (!isCheckedMiddleware) {
			if (Object.prototype.toString.call(middleware) !== '[object Array]') {
				throw new Error("react-hooks: middleware isn't Array");
			}
			isCheckedMiddleware = true;
		}

		//递归调用中间件
		var nextFun = (middleware,action,state,n)=>{
			if(n>middleware.length){
				return state;
			}
			return middleware[n]({state, dispatch})((action)=>{
				return nextFun(middleware, action, state, n+1)
			})(action);
		}

		return nextFun(middleware, action, state, 0);
	};

	//封装 dispath ，在发起真正 dispath 之前，先执行中间件
	var wrapperDispatch = (action) => {
		middlewareReducer({state, dispatch, action});
	};

	const [state, dispatch] = React.useReducer(reducer, initstate || {});

	const AppContext = createCessContext(name);//React.createContext();

	//把 action 连接到 reduex 上
    var connect = function(action){
    	return function(){
    		action.apply(this,arguments)({dispatch:wrapperDispatch, state});
    	}
    }

	const Provider = props => {
		return <AppContext.Provider {...props} value={{state, connect, dispatch:wrapperDispatch}} />;
	};

    return {Provider, connect,state, dispatch:wrapperDispatch, context:AppContext}
}



/*
 * 把多个 reducer 合并为一个 reducer
 *
 */
export function combineReducers(combine){

    return (state, action) => {
        for(var key in combine){
            state[key] = combine[key](state[key], action) || {};
        }
        return {...state};
    }
}